/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/



#if !defined(AFX_PGLCIRCPOLYGONMARKER_H__17503B8F_5BFA_4F5E_A402_AD1B07640464__INCLUDED_)
#define AFX_PGLCIRCPOLYGONMARKER_H__17503B8F_5BFA_4F5E_A402_AD1B07640464__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <pgl/core/PGLMarker.h>
#include <pgl/core/PGLDataVectors.h>

class CPGLCircPolygonMarker;
PGL_DECLARE_SMARTPTR( CPGLCircPolygonMarker );


/*! \brief A polygon inside a circle

	This marker describes a \f$n\f$-gon built inside a circle as described in the picture.
	\image html circpolymarker.png "Classical n-gons"

\par Number of side

  The number of side can be changed dynamically using SetSideCount . 

\par Phase handling

	The phase can be automatically tuned in order to have a side of the n-gon parallel to the x axis.
This option can be enabled/disable using EnableAutoPhase .

\par Helper constructors

  There are a serie of helper constructors for "popular" n-gon:
	- GetTriangle
	- GetSquare
	- GetPentagon
	- GetHexagon


	\ingroup PGLMarkerGroup
*/
class PGLCORE_EXT_CLASS CPGLCircPolygonMarker : public CPGLMarker  
{
PGL_DECLARE_DYNCREATE(CPGLCircPolygonMarker);
public:
	//! \name Constructors
	//@{
	//! Default constructor
	CPGLCircPolygonMarker(const CPGLColor& _color=CPGLColor(), const CPGLColor& _FillColor=CPGLColor(1,1,1,1), double dRadius =  4, bool bFilled = false, UINT uSideCount = 3);
	//! Copy constructor
	CPGLCircPolygonMarker(const CPGLCircPolygonMarker& p){*this = p;};
	//! Assignement constructor
	CPGLCircPolygonMarker& operator = (const CPGLCircPolygonMarker& p);
	virtual ~CPGLCircPolygonMarker(){};
	//@}

	//! \name Helper constructors
	//@{
	//! returns a triangle
	static CPGLCircPolygonMarkerPtr GetTriangle( double dRadius=4, bool bFilled=false );
	//! returns a square
	static CPGLCircPolygonMarkerPtr GetSquare( double dRadius=4, bool bFilled=false );
	//! return a pentagon
	static CPGLCircPolygonMarkerPtr GetPentagon( double dRadius=4, bool bFilled=false );
	//! returns an hexagon
	static CPGLCircPolygonMarkerPtr GetHexagon( double dRadius=4, bool bFilled=false );
	//@}

	//! Polygon description
	//@{
	/*! \brief  Sets the number of side of the polygon

	\param uSideCount, number of side of the polygon. Minimum value is 3.
	*/
	void SetSideCount( UINT uSideCount )		{	m_uSideCount = __max( 3, uSideCount );  NeedGeneration();};
	//! Return the number of side of the polygon
	UINT GetSideCount() const					{	return m_uSideCount;};
	//@}

	//! \name Radius and phase
	//@{
	//! sets the marker radius
	virtual void SetRadius( double radius )		{	CPGLMarker::SetRadius(radius); NeedGeneration();};
	//! sets the marker phase
	virtual void SetPhase( double p)			{	CPGLMarker::SetPhase(p); NeedGeneration();};
	/*! Adjust phase

	Adjust phase to have one of the side paralle to x. The corresponding phase is the solution of
	\f[ cos(\phi) = -cos( \phi + \frac{n-1}{n} 2 \pi ) \rightarrow \phi = \pi \left( \frac{1}{2} - \frac{n-1}{n} \right) \f]
	where \f$n\f$ is the number of sides.
	*/
	void AdjustPhase()							{	SetPhase(PGL_PI*( 0.5 - (m_uSideCount-1.0)/(double)m_uSideCount));};
	//! Enables, disable automatic phase adjustement
	void EnableAutoPhase(bool yes)				{	m_bAutoPhase = yes;};
	//! Is auto phase enabled (default is true)
	bool IsAutoPhase() const					{	return m_bAutoPhase;};
	//@}

	//! \name Polygon generation
	//@{
	//! tells the object that regeneration of the polygon corners is needed
	void NeedGeneration()						{	m_bNeedGeneration = true;};
	//! returns true if generation is needed...
	bool IsGenerationNeeded() const				{	return m_bNeedGeneration;};
	//! generate corners
	void Generate(bool bLegend = false);
	//@}

	//! \name Plotting functions
	//@{
	//! Main plotting function
	void PlotGfx(gfxinterface::CGfxInterface& gfx, CPGLDataPtr pDataX, CPGLDataPtr pDataY);
	//! Legend plotting
	void PlotLegendGfx(gfxinterface::CGfxInterface& gfx, float x, float y);
	//! returns line type
	DWORD  GetLineType() const		{	return CPGLMarker::GetLineType() | gfxinterface::LineTypeClosed;};
	//@}

	//! \name Serialize functions
	//@{
	//! Serialiation to XML
	void SerializeXML(CPGLArchive& ar);

	//! Debuggin functions
	#ifdef _DEBUG
		//! MFC Dump
	    virtual void Dump( CDumpContext& dc ) const;
		//! MFC AssertValid
	    virtual void AssertValid() const;   
	#endif
	//@}

private:
	//! \name Attributes
	//@{
	//! number of sides (minimum 3)
	UINT m_uSideCount;
	//! x position of corners
	CPGLVectorF m_vX;
	//! y position of corners
	CPGLVectorF m_vY;
	//! true if points need regeneration
	bool m_bNeedGeneration;
	//! true if auto phase adjustement
	bool m_bAutoPhase;
	//@}
};

#endif // !defined(AFX_PGLCIRCPOLYGONMARKER_H__17503B8F_5BFA_4F5E_A402_AD1B07640464__INCLUDED_)
